package model;

import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author gilaquila
 */
public class ScoreDB {

    private final static List<Score> scoreList = new ArrayList<>();

    private static final String FILE_NAME = "highScore.score";
    private static final int KEY = 24352321;

    private ScoreDB() {
//        load();
    }

    public static void submitScore(String username, Integer points) {
        submitScore(new Score(username, points));
    }

    public static void submitScore(Score s) {
        scoreList.add(s);

        Thread a = new Thread("submitThread") {

            @Override
            public void run() {
                synchronized (scoreList) {
                    Collections.sort(scoreList);
                
                    save();
                }
            }
        };

        a.start();
    }

    public static Score[] getHighScore() {
        
        return scoreList.toArray(new Score[scoreList.size()]);
    }

    private static void save() {
        try {
            try (BufferedWriter br = new BufferedWriter(new FileWriter(FILE_NAME))) {
                
                for (Score score : scoreList) {
                    br.write(encrypt(score.username + " " + score.points + " " + score.hashCode()));
                    br.newLine();
                    br.flush();
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(ScoreDB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private static void load() {
        try (BufferedReader br = new BufferedReader(new FileReader(FILE_NAME))) {
            
            String read = br.readLine();
            
            while (read != null) {
                StringTokenizer st = new StringTokenizer(decrypt(read));
                
                Score s = new Score(st.nextToken(), Integer.parseInt(st.nextToken()));
                
                if(st.hasMoreTokens() && 
                        Integer.valueOf(st.nextToken()).equals(s.hashCode()) && 
                        !scoreList.contains(s)){
                    scoreList.add(s);
                }
                
                read = br.readLine();
            }
        } catch (FileNotFoundException ex) {
            
            //The file will be created after doing a complete game
            
        } catch (IOException ex) {
            Logger.getLogger(ScoreDB.class.getName()).log(Level.SEVERE, null, ex);
        }

        Collections.sort(scoreList);
    }
    
    private static String encrypt(String s){
        
//        StringBuilder stb = new StringBuilder();
//        
//        for (int i = 0; i < s.length(); i++) {
//            stb.append(s.charAt(i)-32 * (i % 2 == 0 ? KEY : Integer.reverse(KEY))).append("||||");
//        }
//        
//        return stb.toString();
        
        return s;
    }
    
    private static String decrypt(String s){
//        StringTokenizer st = new StringTokenizer(s, "||||");
//        int initialCount = st.countTokens();
//        
//        StringBuilder parsed = new StringBuilder();
//        
//        for (; st.hasMoreTokens();) {
//            Integer num = Integer.getInteger(st.nextToken());
//            num /= ((initialCount - st.countTokens())% 2 == 0 ? KEY : Integer.reverse(KEY)) + 32;
//            
//            parsed.append(num);
//        }
//        
//        return parsed.toString();
        
        return s;
    }
    
    private static final ScoreDB INSTANCE;

    static {
        INSTANCE = new ScoreDB();
    }

    public static class Score implements Serializable, Comparable {

        private final String username;
        private final Integer points;

        public Score(String username, Integer points) {
            this.username = username;
            this.points = points;
        }

        public String getUsername() {
            return username;
        }

        public Integer getPoints() {
            return points;
        }

        @Override
        public String toString() {
            return username + " " + points;
        }

        @Override
        public int compareTo(Object o) {
            if (o instanceof Score) {
                Score s = (Score) o;

                return -points.compareTo(s.points);
            }

            throw new ClassCastException();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Score other = (Score) obj;
            if (!Objects.equals(this.username, other.username)) {
                return false;
            }
            return Objects.equals(this.points, other.points);
        }

        @Override
        public int hashCode() {
            int hash = 26597;
            hash = 44071 * hash + Objects.hashCode(this.username);
            hash = 8101 * hash + Objects.hashCode(this.points);
            return hash;
        }
    }
}
